package com.example.taskscheduling.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 定时任务调度服务类
 * 用于演示Spring的定时任务功能，包含多种调度方式的定时任务示例
 * 需在启动类添加@EnableScheduling注解开启定时任务支持
 */
@Service // 标识为Spring服务层组件，由Spring容器管理
public class ScheduledTaskService {

    // 定义日期时间格式化器，指定格式为"年-月-日 时:分:秒"
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // 计数器，用于记录各定时任务的执行次数
    private Integer count1 = 1;
    private Integer count2 = 1;
    private Integer count3 = 1;

    /**
     * 基于fixedRate的定时任务
     * fixedRate：以上一次任务开始时间为基准，间隔固定时间后执行下一次任务
     * 特点：无论上一次任务是否执行完毕，到时间就会启动新的任务
     *
     * @Scheduled(fixedRate = 2000)：表示每2000毫秒（2秒）执行一次
     */
    @Scheduled(fixedRate = 2000)
    public void fixedRateScheduledTask() {
        // 打印任务执行信息：任务标识、执行次数和当前时间
        System.out.println("【1】fixedRate第" + count1 + "次执行，当前时间为：" + LocalDateTime.now().format(dtf));
        count1++; // 计数器自增
    }

    /**
     * 基于fixedDelay的定时任务
     * fixedDelay：以上一次任务执行结束时间为基准，间隔固定时间后执行下一次任务
     * 特点：必须等待上一次任务完全执行完毕，才会计算间隔时间
     *
     * @throws InterruptedException 线程休眠可能抛出的中断异常
     * @Scheduled(fixedDelay = 1000)：表示上一次任务结束后，间隔1000毫秒（1秒）执行下一次
     */
    @Scheduled(fixedDelay = 1000)
    public void fixedDelayScheduledTask() throws InterruptedException {
        // 打印任务执行信息
        System.out.println("【2】fixedDelay第" + count2 + "次执行，当前时间为：" + LocalDateTime.now().format(dtf));
        count2++; // 计数器自增

        // 模拟任务执行耗时（休眠2000毫秒）
        // 实际执行间隔 = 任务耗时（2秒） + fixedDelay（1秒） = 约3秒
        Thread.sleep(2000);
    }

    /**
     * 基于cron表达式的定时任务
     * cron表达式：一种灵活的时间表达式，可精确指定任务的执行时间
     * 适用于复杂的定时需求（如每天凌晨3点执行、每周一上午执行等）
     *
     * @Scheduled(cron = "* * * * * ?")：表示每秒执行一次
     * cron表达式格式：秒 分 时 日 月 周 年（年可选）
     */
    /**
     * cron表达式格式详解（6或7个字段，空格分隔）
     * 完整格式：[秒] [分] [时] [日] [月] [周] ([年])  （年为可选字段）
     * <p>
     * 各字段取值与写法示例：
     * 1. 秒（0-59）
     * - *    ：每秒执行（如 "*"）
     * - 0/10 ：从0秒开始，每10秒执行一次（如 "0/10"）
     * - 30    ：每分钟的30秒执行（如 "30"）
     * - 10-20 ：每秒的10-20秒之间，每秒执行（如 "10-20"）
     * - 10,20,30：每秒的10、20、30秒执行（如 "10,20,30"）
     * <p>
     * 2. 分（0-59）
     * - 0    ：每小时的0分执行（如 "0"）
     * - 0/30 ：从0分开始，每30分钟执行（如 "0/30"）
     * - 10-20 ：每小时的10-20分之间，每分钟执行（如 "10-20"）
     * <p>
     * 3. 时（0-23）
     * - 8    ：每天早上8点执行（如 "8"）
     * - 8-18 ：每天8点到18点之间，每小时执行（如 "8-18"）
     * - 8,12,18：每天8点、12点、18点执行（如 "8,12,18"）
     * <p>
     * 4. 日（1-31）
     * - 1    ：每月1日执行（如 "1"）
     * - 1-5 ：每月1-5日，每天执行（如 "1-5"）
     * - L    ：每月最后一天执行（如 "L"）
     * - 15W ：每月15日最近的工作日（如 "15W"）
     * - ?    ：不指定具体日期（与周字段配合使用，避免冲突）
     * <p>
     * 5. 月（1-12 或 JAN-DEC）
     * - 1    ：每年1月执行（如 "1" 或 "JAN"）
     * - 1-3 ：每年1-3月，每月执行（如 "1-3" 或 "JAN-MAR"）
     * - * / 2 ：每2个月执行一次（如 "* / 2"）
     * <p>
     * 6. 周（1-7 或 SUN-SAT，1=周日，7=周六）
     * - 1    ：每周日执行（如 "1" 或 "SUN"）
     * - 1-5 ：每周一至周五执行（如 "1-5" 或 "MON-FRI"）
     * - 6L   ：每月最后一个周五执行（如 "6L"）
     * - 6#3 ：每月第3个周五执行（如 "6#3"）
     * - ?    ：不指定具体周几（与日字段配合使用，避免冲突）
     * <p>
     * 7. 年（可选，1970-2099）
     * - 2023 ：仅2023年执行（如 "2023"）
     * - 2023-2025：2023-2025年执行（如 "2023-2025"）
     * - 省略时表示所有年份
     * <p>
     * 常用示例：
     * - "0 0 12 * * ?"         ：每天中午12点执行
     * - "0 30 8 ? * MON-FRI"  ：每周一至周五早上8:30执行
     * - "0 0 1 * * 6L"        ：每月最后一个周六凌晨1点执行
     * - "0/30 * * * * ?"      ：每30秒执行一次
     * - "0 0 12 15 * ? 2023"  ：2023年每月15日中午12点执行
     */
    @Scheduled(cron = "* * * * * ?")
    public void cronScheduledTask() {
        // 打印任务执行信息
        System.out.println("【3】cron第" + count3 + "次执行，当前时间为：" + LocalDateTime.now().format(dtf));
        count3++; // 计数器自增
    }
}